package nessie;

/**
 * registers. the wet dream of every programmer(10 years ago).
 * nothing special here except the P(for pStatus register<silent 'p'>) register.
 */
public class Registers {

    private Registers() {
    }

    public static void init() {
        A = P = X = Y = 0;
        SP = (byte) 0xFF;
        PC = (short) Memory._ROM;
    }
    /**Accumulator*/
    public static byte A;
    /**Processor status register*/
    private static byte P;
    /**index register X*/
    public static byte X;
    /**index register Y*/
    public static byte Y;
    /**Program counter*/
    public static short PC;
    /**Stack Pointer*/
    protected static byte SP;

    /**@return unsigned PC*/
    public static int getUnsignerPC() {
        return PC & 0xFFFF;
    }
    /**binary masks for flags*/
    private static final int C = 0b00000001,
            Z = 0b00000010,
            I = 0b00000100,
            D = 0b00001000,
            B = 0b00010000,
            V = 0b01000000,
            N = 0b10000000;
    private static final int ALWAYS_HONEST = 0b0010_0000;

    /**
     * http://wiki.nesdev.com/w/index.php/CPU_status_flag_behavior
     */
    public static byte getP() {
        //NV BDIZC
        P = (byte) ((Flags.C & C)
                | (Flags.Z ? Z : 0)
                | (Flags.I ? I : 0)
                | (Flags.D ? D : 0)
                | (Flags.B ? B : 0)
                | ALWAYS_HONEST
                | (Flags.V ? V : 0)
                | (Flags.N ? N : 0));
        return P;
    }

    public static void setP(byte P) {
        //CZIDB VN
        Registers.P = P;
        Flags.C = (byte) (P & C);
        Flags.Z = ((P & Z) == Z);
        Flags.I = ((P & I) == I);
        Flags.D = ((P & D) == D);
        Flags.B = ((P & B) == B);
        Flags.V = ((P & V) == V);
        Flags.N = ((P & N) == N);
    }
}
